unit mainform;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LSControls, Forms, Controls, Graphics, Dialogs,
  StdCtrls, Menus, ExtCtrls, ComCtrls, nkTitleBar, nkResizer, ubarcodes,
  LR_DB_Zeos, LR_Class, LR_Desgn, LR_DBSet, Printers, fpreport, IniFiles,
  rxctrls, rxswitch, rxmemds, BCLabel, BCButton, fpJson, MD5, IdGlobal, intf,
  LMessages;

type

  { TfrmMain }

  TfrmMain = class(TForm)
    autoprint: TRxSwitch;
    qrcode: TBarcodeQR;
    BCButton1: TBCButton;
    BCButton2: TBCButton;
    BCButton3: TBCButton;
    BCLabel1: TBCLabel;
    frDBDataSet1: TfrDBDataSet;
    Image1: TImage;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    ls: TListView;
    MenuItem1: TMenuItem;
    MenuItem2: TMenuItem;
    MenuItem3: TMenuItem;
    nkResizer1: TnkResizer;
    nkTitleBar2: TnkTitleBar;
    Panel1: TPanel;
    Panel2: TPanel;
    Panel3: TPanel;
    report: TfrReport;
    reportdesigner: TfrDesigner;
    mem: TRxMemoryData;
    printtimer: TTimer;
    TrayPopup: TPopupMenu;
    RxSpeedButton1: TRxSpeedButton;
    Tray: TLSTrayIcon;
    procedure autoprintClick(Sender: TObject);
    procedure BCButton1Click(Sender: TObject);
    procedure BCButton3Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure Image1Click(Sender: TObject);
    procedure MenuItem1Click(Sender: TObject);
    procedure MenuItem2Click(Sender: TObject);
    procedure Panel1DblClick(Sender: TObject);
    procedure printtimerTimer(Sender: TObject);
    procedure reportEnterRect(Memo: TStringList; View: TfrView);
    procedure reportGetValue(const ParName: String; var ParValue: Variant);
    procedure RxSpeedButton1Click(Sender: TObject);
    procedure TrayDblClick(Sender: TObject);
  private
    procedure handler_MSG_PUBLISH_MESSAGE(var Message: TLMessage); message MSG_PUBLISH_MESSAGE;
    procedure handler_MSG_CONFIG_CHANGED(var Message: TLMessage);message MSG_CONFIG_CHANGED;
  public
    IsPrinting:boolean;//是否正在打印
    PrintIndex:integer;//正在打印的Listitem序号
    procedure InitWebServerConfig;//初始化webSERVER设置
    function DoLogin(AUname,APwd:string):string;//执行登录过程
    procedure Log(AText:string);//显示信息
    procedure LoadCustomConfig;//读取设置
    procedure UpdateDisplayConfig;//更新显示设置信息

  end;

var
  frmMain: TfrmMain;

implementation

uses
  datamodule, settingform;

{$R *.frm}
{ TfrmMain }

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Tray.Icon.LoadFromResourceName(HInstance,'DEACTIVE');
  Self.Color:=$005F4A21;
  ls.Items.Clear;
end;

procedure TfrmMain.FormShow(Sender: TObject);
begin
  InitWebServerConfig;
  LoadCustomConfig;
  UpdateDisplayConfig;
  Label2.Caption:='未连接网络';
  Label2.Font.Color:=$0000ff;
end;

procedure TfrmMain.Image1Click(Sender: TObject);
begin
  //设置机台编号
  frmSetting:=TfrmSetting.Create(Application);
  frmSetting.Show;
end;

procedure TfrmMain.MenuItem1Click(Sender: TObject);
begin
  if Dm.conn.Connected then
    Dm.AddSysLog('处方打印断开网络',Dm.PrinterID);
  Application.Terminate;
end;

procedure TfrmMain.MenuItem2Click(Sender: TObject);
begin
  Tray.RestoreMainForm;
end;

procedure TfrmMain.Panel1DblClick(Sender: TObject);
begin
  //MEM添加演示数据
  mem.Open;
  mem.Append;
  mem.FieldByName('code_std').AsString:='0001';
  mem.FieldByName('name_std').AsString:='阿司匹林';
  mem.Post;
  mem.Append;
  mem.FieldByName('code_std').AsString:='0002';
  mem.FieldByName('name_std').AsString:='青霉素';
  mem.Post;
  report.ShowReport;
end;

procedure TfrmMain.printtimerTimer(Sender: TObject);
var
  mDanhao,mJiuzhenkahao,mDoctorUUID,mShenheUUID,mKaifangshijian:string;
  mXingming,mXingbie,mNianling:string;
  i:integer;
begin
  if Self.IsPrinting=False then
  begin
    Self.PrintIndex:=-1;
    //没有打印任务，找到第一个要打印的任务
    if ls.Items.Count>0 then
    begin
      for i:=0 to ls.Items.Count-1 do
      begin
        if ls.Items.Item[i].SubItems.Strings[1]='等待' then
        begin
          //设置打印状态未True
          Self.IsPrinting:=True;
          mDanhao:=ls.Items.Item[i].Caption;
          PrintIndex:=i;
          //查询处方明细数据写入内存表
          with Dm.pubQry do
          begin
            Close;
            Sql.Clear;
            Sql.Add('select * from dat_chufang_detail where danhao=:danhao');
            Params.ParamByName('danhao').AsString:=mDanhao;
            Open;
            First;
            //清空内存表
            mem.Close;
            mem.Open;
            //写入内存表
            while not Eof do
            begin
              mem.Append;
              mem.FieldByName('code_std').AsString:=FieldByName('code_std').AsString;
              mem.FieldByName('name_std').AsString:=FieldByName('name_std').AsString;
              mem.FieldByName('guige').AsString:=FieldByName('guige').AsString;
              mem.FieldByName('jiliang').AsString:=FormatFloat('#0.0000',FieldbyName('jiliang').AsFloat)+FieldByName('danwei_jiliang').AsString;
              mem.FieldByName('shuliang').AsString:=FormatFloat('#0.0000',FieldbyName('shuliang').AsFloat)+FieldByName('danwei_baozhuang').AsString;
              mem.FieldByName('yongfa').AsString:=FieldByName('yongfa').AsString;
              mem.FieldByName('pinlv').AsString:=FieldByName('pinlv').AsString;
              mem.Post;
              Next;
            end;
            //查询患者就诊卡号和医生UUID、开方时间
            Close;
            Sql.Clear;
            Sql.Add('select * from dat_chufang_master where danhao=:danhao');
            Params.ParamByName('danhao').AsString:=mDanhao;
            Open;
            First;
            if not Eof then
            begin
              mDoctorUUID:=FieldByName('doctor_uuid').AsString;
              mShenheUUID:=FieldByName('shenhe_uuid').AsString;
              mJiuzhenkahao:=FieldByName('jiuzhenkahao').AsString;
              mKaifangshijian:=FormatDatetime('yyyy-mm-dd hh:mm',FieldByName('kaifangshijian').AsDateTime);
            end;
            //根据就诊卡号查询患者信息
            Close;
            Sql.Clear;
            Sql.Add('select * from cfg_huanzhexinxi where jiuzhenka=:jiuzhenkahao');
            Params.ParamByName('jiuzhenkahao').AsString:=mJiuzhenkahao;
            Open;
            First;
            if not Eof then
            begin
              mxingming:=FieldbyName('xingming').AsString;
              mXingbie:=FieldByName('xingbie').AsString;
              mNianling:=inttostr(FieldByName('nianling').AsInteger);
            end;
            //参数添加到listitem的subitems中
            ls.Items.Item[i].SubItems.Add(mDanhao);//单号 index=2
            ls.Items.Item[i].SubItems.Add(mKaifangshijian);//开方时间 index=3
            ls.Items.Item[i].SubItems.Add(mXingming);//患者姓名 index=4
            ls.Items.Item[i].SubItems.Add(mXingbie);//患者性别 index=5
            ls.Items.Item[i].SubItems.Add(mNianling);//患者年龄 index=6
            ls.Items.Item[i].SubItems.Add(mDoctorUUID);//医生UUID index=7
            ls.Items.Item[i].SubItems.Add(mShenheUUID);//审方人UUID index=8
          end;
          //设置状态信息
          ls.Items.Item[i].SubItems.Strings[1]:='打印中';
          //打印
          report.ChangePrinter(Printer.PrinterIndex, Printer.Printers.IndexOf(Dm.PrinterName));
          //report.PrepareReport;
          report.ShowReport;//打印预览
          //report.PrintPreparedReport(1,report.EMFPages.Count,1); //打印
          //打印完毕，设置状态信息
          ls.Items.Item[i].SubItems.Strings[1]:='已打印';
          Self.IsPrinting:=False;
          //记录日志
          Dm.AddSysLog('打印处方',Dm.PrinterID+':'+mDanhao);
          //退出循环
          Break;
        end;
      end;
    end;
  end;
end;

procedure TfrmMain.reportEnterRect(Memo: TStringList; View: TfrView);
var
  mStream:TMemoryStream;
  mBitmap:TBitmap;
  mItem:TListitem;
begin
  if (View is TfrPictureView) then
  begin
    {if (View as TfrPictureView).Name = 'qrcode' then
    begin
      mStream:=TMemoryStream.Create;
      qrcode.Text:='http://www.baidu.com';
      qrcode.Update;
      mBitmap:=TBitmap.Create;
      mBitmap.Width:=qrCode.Width;
      mBitmap.Height:=qrCode.Height;
      mBitmap.Canvas.Pen.Color:=clWhite;
      mBitmap.Canvas.Brush.Color:=clWhite;
      mBitmap.Canvas.Rectangle(0,0,mBitmap.Width,mBitmap.Height);
      qrcode.PaintOnCanvas(mBitmap.Canvas,qrcode.ClientRect);
      mBitmap.SaveToStream(mStream);
      mStream.Seek(0,soBeginning);
      (View as TfrPictureView).Picture.LoadFromStream(mStream);
      mBitmap.Free;
      mStream.Free;
    end;}
    if (View as TfrPictureView).Name = 'logo' then
    begin
      mBitmap:=TBitmap.Create;
      mBitmap.LoadFromFile(ExtractFilepath(Application.ExeName)+'logo.bmp');
      mStream:=TMemoryStream.Create;
      mBitmap.SaveToStream(mStream);
      mStream.Seek(0,soBeginning);
      (View as TfrPictureView).Picture.LoadFromStream(mStream);
      mBitmap.Free;
      mStream.Free;
    end;
    if (View as TfrPictureView).Name = 'doctor_sign' then
    begin
      mStream:=TMemoryStream.Create;
      mItem:=ls.Items.Item[Self.PrintIndex];
      try
        //ShowMessage(Dm.WebServer+URL_USIGN+'/'+mItem.SubItems.Strings[7]);
        Dm.http.Get(Dm.WebServer+URL_USIGN+'/'+mItem.SubItems.Strings[7],mStream);
        mStream.Seek(0,soBeginning);
        (View as TfrPictureView).Picture.LoadFromStream(mStream);
      finally
      end;
      mStream.Free;
    end;
    if (View as TfrPictureView).Name = 'shenhe_sign' then
    begin
      mStream:=TMemoryStream.Create;
      mItem:=ls.Items.Item[Self.PrintIndex];
      try
        //ShowMessage(Dm.WebServer+URL_USIGN+'/'+mItem.SubItems.Strings[8]);
        Dm.http.Get(Dm.WebServer+URL_USIGN+'/'+mItem.SubItems.Strings[8],mStream);
        mStream.Seek(0,soBeginning);
        (View as TfrPictureView).Picture.LoadFromStream(mStream);
      finally
      end;
      mStream.Free;
    end;
  end;
end;

procedure TfrmMain.reportGetValue(const ParName: String; var ParValue: Variant);
var
  mItem:TListItem;
begin
  //向打印模板传递变量
  if Self.PrintIndex=-1 then Exit;
{            ls.Items.Item[i].SubItems.Add(mKaifangshijian);//开方时间 index=3
            ls.Items.Item[i].SubItems.Add(mXingming);//患者姓名 index=4
            ls.Items.Item[i].SubItems.Add(mXingbie);//患者性别 index=5
            ls.Items.Item[i].SubItems.Add(mNianling);//患者年龄 index=6
            ls.Items.Item[i].SubItems.Add(mDoctorUUID);//医生UUID index=7
            ls.Items.Item[i].SubItems.Add(mShenheUUID);//审方人UUID index=8
}
  mItem:=ls.Items.Item[PrintIndex];
  if ParName='danhao' then
    ParValue:=mItem.Caption;
  if ParName='kaifangshijian' then
    ParValue:=mItem.SubItems.Strings[3];
  if ParName='xingming' then
    ParValue:=mItem.SubItems.Strings[4];
  if ParName='xingbie' then
    ParValue:=mItem.SubItems.Strings[5];
  if ParName='nianling' then
    ParValue:=mItem.SubItems.Strings[6];

end;

procedure TfrmMain.RxSpeedButton1Click(Sender: TObject);
begin
  Self.Hide;
end;

procedure TfrmMain.TrayDblClick(Sender: TObject);
begin
  Tray.RestoreMainForm;
end;

procedure TfrmMain.handler_MSG_PUBLISH_MESSAGE(var Message: TLMessage);
var
  m:string;
  mDanhao:string;
begin
  //处理处方打印消息
  m:=string(Pointer(Message.wParam)^);
  mDanhao:=Dm.ExtractDanhaoFromJsonString(m);
  if Trim(mDanhao)<>'' then
  begin
    //添加到列表中
    ls.BeginUpdate;
    with ls.Items.Add do
    begin
      Caption:=mDanhao;
      SubItems.Add(Formatdatetime('yyyy-mm-dd hh:mm:ss', Now()));
      SubItems.Add('等待');
    end;
    ls.EndUpdate;
  end;
end;

procedure TfrmMain.handler_MSG_CONFIG_CHANGED(var Message: TLMessage);
begin
  report.LoadFromFile(Dm.PrintTemplate);
  Self.UpdateDisplayConfig;
end;

procedure TfrmMain.InitWebServerConfig;
var
  mIni:TIniFile;
begin
  mIni:=TIniFile.Create(ExtractFilepath(Application.ExeName)+'config.ini');
  Dm.WebServer:=mIni.ReadString('common','server','http://192.168.0.95:8989');
  mIni.Free;
end;

function TfrmMain.DoLogin(AUname, APwd: string): string;
var
  mUrl:string;
  mR:string;
  mStream:TStringStream;
  mJson:TJsonData;
  mCode:string;
  mP:string;
begin
  Result:='';
  mP:=MD5Print(MD5String(Trim(APwd)));
  //开始登录
  Log('正在登录……');
  mUrl:=Dm.WebServer+URL_LOGIN+'?gonghao='+AUname+'&pwd='+mP+'&kind=p';
  try
    mR:=dm.http.Get(mUrl, IndyTextEncoding_UTF8);
  except
    Result:='无法连接到服务器';
    Exit;
  end;
  mStream:=TStringStream.Create(mR,TEncoding.UTF8);
  mStream.Seek(0,soBeginning);
  mJson:=GetJson(mStream, True);
  //解析JSON中的登录状态码
  try
    mCode:=mJson.FindPath('code').AsString;
  except
    Result:='错误：服务器未正确返回信息';
    exit;
  end;
  if mCode='404' then
  begin
    Result:='工号和密码不匹配，请重新登录';
    Exit;
  end;
  if mCode='501' then
  begin
    Result:='系统模块需更新，请联系管理员。';
    Exit;
  end;
  if mCode='200' then
  begin
    Log('正在设置环境……');
    //登录成功，解析返回的参数
    Dm.UName:=mJson.FindPath('uname').AsString;
    Dm.UGonghao:=mJson.FindPath('ugonghao').AsString;
    Dm.UUID:=mJson.FindPath('uuid').AsString;
    Dm.USign:=mJson.FindPath('usign').AsString;
    Dm.UOffice:=mJson.FindPath('uoffice').AsString;
    Dm.DB_Host:=mJson.FindPath('db_host').AsString;
    Dm.DB_Name:=mJson.FindPath('db_name').AsString;
    Dm.DB_Port:=strtoint(mJson.FindPath('db_port').AsString);
    Dm.DB_Pwd:=mJson.FindPath('db_pwd').AsString;
    Dm.DB_User:=mJson.FindPath('db_user').AsString;
    Dm.Use_Local_goods:=mJson.FindPath('db_use_local_goods').AsString='true';
    Dm.Company:=mJson.FindPath('company').AsString;
    Dm.Department:=mJson.FindPath('db_owner').AsString;
    Dm.DB_MsgHost:=mJson.FindPath('db_msghost').AsString;
    Dm.DB_MsgPort:=strtoint(mJson.FindPath('db_msgport').AsString);
    //连接数据库
    Dm.conn.HostName:=Dm.DB_Host;
    Dm.conn.Database:=Dm.DB_Name;
    Dm.conn.User:=Dm.DB_User;
    Dm.conn.Password:=Dm.DB_Pwd;
    Dm.conn.Port:=Dm.DB_Port;
    Dm.conn.LibraryLocation:=ExtractFilepath(Application.ExeName)+'libpq.dll';
    try
      Dm.conn.Connect;
    except
      Result:='无法连接数据库，请联系管理员';
      Exit;
    end;
    //连接消息服务器
    Dm.CreateMqttClient;
    if Dm.ConectMqttServer=False then
    begin
      Result:='未连接到消息服务，某些功能可能会受影响，请联系管理员。';
      Exit;
    end;
    Dm.MqttAutoPing.Enabled:=True;//开始Ping定时器
    //打开对应的数据表
  end;
end;

procedure TfrmMain.Log(AText: string);
begin

end;

procedure TfrmMain.LoadCustomConfig;
var
  mIni:TIniFile;
begin
  mIni:=TIniFile.Create(ExtractFilepath(Application.ExeName)+'custom.ini');
  Dm.PrinterName:=mIni.ReadString('cfprint','name','');
  Dm.PrinterID:=mIni.ReadString('cfprint','id','');
  Dm.PrintTemplate:=mIni.ReadString('cfprint','tpl','');
  mIni.Free;
  //读入模板信息
  if Dm.PrintTemplate<>'' then
    if FileExists(Dm.PrintTemplate) then
      report.LoadFromFile(Dm.PrintTemplate);
end;

procedure TfrmMain.UpdateDisplayConfig;
begin
  //设置修改消息
  if Trim(Dm.PrinterID)='' then
    Label1.Caption:='未设置'
  else
    Label1.Caption:=Trim(Dm.PrinterID);
  if Trim(Dm.PrinterName)='' then
    Label4.Caption:='未选择打印机'
  else
    Label4.Caption:='已选择打印机'+Trim(Dm.PrinterName);
  if autoprint.StateOn=sw_on then
    Label3.Caption:='已启动自动打印'
  else
    Label3.Caption:='已关闭自动打印';
  if Trim(Dm.PrintTemplate)='' then
    Label5.Caption:='未设置模板'
  else
    Label5.Caption:='已设置模板';
end;

procedure TfrmMain.BCButton1Click(Sender: TObject);
var
  mR:String;
begin
  //先检查参数是否设置好
  if (Trim(Dm.PrinterID)='') or (Trim(Dm.PrinterName)='') or (Trim(Dm.PrintTemplate)='') then
  begin
    MessageDlg('参数未设置完整，请先完善参数设置。',mtWarning,[mbOK],0);
    Exit;
  end;
  mR:=Self.DoLogin('cfprint','123456');
  if Trim(mR)<>'' then
  begin
    Tray.BalloonHint:=mR;
    Tray.ShowBalloonHint;
    Exit;
  end;
  //登录成功，修改图标
  Tray.Icon.LoadFromResourceName(HInstance,'ACTIVE');
  //修改按钮颜色和标签
  BCButton1.StateNormal.Background.Color:=clTeal;
  BCButton1.Caption:='已连接';
  Label2.Caption:='已连接网络';
  Label2.Font.Color:=clLime;
  Tray.BalloonHint:='处方打印网络服务已启动。';
  Tray.ShowBalloonHint;
  Dm.AddSysLog('处方打印连接入网',Dm.PrinterID);
  //打开打印定时器
  PrintTimer.Enabled:=True;
end;

procedure TfrmMain.BCButton3Click(Sender: TObject);
begin
  //设置打印模板
  report.DesignReport;
end;

procedure TfrmMain.autoprintClick(Sender: TObject);
begin
  Self.UpdateDisplayConfig;
end;

end.

